#pragma once
#include <vector>
#include <unordered_map>
#include <type_traits>
#include <stdexcept>

#include "ClientThreadExecution.hpp"
#include "../interface/ClientExecutionInterface.hpp"

#include "../../type/ClientType.hpp"


/**
 * 执行器启动信息类
 */
class ExecutionStartInformation {
private:
    ClientType::EXECUTION_TYPE m_executionType;
    //是否多线程启动
    bool m_isThread;
public:

    ExecutionStartInformation() {
        this->m_isThread = false;
    }

    /**
     *
     * @param executionType
     * @param isThread
     */
    ExecutionStartInformation(ClientType::EXECUTION_TYPE executionType, const bool isThread) {
        this->m_executionType = executionType;
        this->m_isThread = isThread;
    }

    /**
     *
     * @return
     */
    ClientType::EXECUTION_TYPE getExecutionType() const{
        return this->m_executionType;
    }

    /**
     *
     * @return
     */
    bool needToThreadStart() const {
        return this->m_isThread;
    }

    ~ExecutionStartInformation() {}

};

/**
 * 服务器主执行器
 */
class ClientMainExecution :public ClientExecutionInterface{

private:
    static ClientType::EXECUTION_TYPE executionType;

    //所有要装配的执行器的类型数组
    static const std::vector<ExecutionStartInformation> executionStartInformationsVector;


    //客户端的执行器
    std::unordered_map<ClientType::EXECUTION_TYPE, ClientExecutionInterface*> m_executionsMap;

    //执行器工厂
    typename ClassReflectionTool::ClassFactory<ClientType::EXECUTION_TYPE>*  m_exeFactory = nullptr;



public:

    //设置配类执行器为友元类
    friend class ClientConfigExecution;





private:

    /**
     * 装配执行器终结条件
     */
    void assemblyExecutions(){}


    /**
     * 初始化执行器
     * @param executionType
     * @return
     */
    ClientExecutionInterface* initializeGetExecution(ClientType::EXECUTION_TYPE executionType) {
        auto it = this->m_executionsMap.find(executionType);
        if (it == this->m_executionsMap.end()) {
            //初始化执行器
            it = this->m_executionsMap.emplace(
                executionType,
                (ClientExecutionInterface*)this->m_exeFactory->createClass(executionType)).first;
        }
        return it->second;

    }





    /**
     * 获取已经装配的执行器
     * @return
     */
    std::unordered_map<ClientType::EXECUTION_TYPE, ClientExecutionInterface*>& getExecutions() {
        return this->m_executionsMap;
    }





    /**
     *重写启动回调函数
     * @return
     */
    bool startCallBackFunction() override {


        //初始化执行器工厂
        this->m_exeFactory = ClassReflectionTool::ClassFactory<ClientType::EXECUTION_TYPE>::getSingleton();


        //初始化获取多线程执行器
        ClientThreadExecution* threadExecution = (ClientThreadExecution*)this->initializeGetExecution(ClientType::CLIENT_THREAD_EXECUTION);


        ClientExecutionInterface* startExecution = nullptr;

        //依次启动执行器
        for (size_t i = 0; i < this->executionStartInformationsVector.size(); i++) {
            ClientType::EXECUTION_TYPE executionType = this->executionStartInformationsVector[i].getExecutionType();

            //初始化获取执行器
            startExecution = this->initializeGetExecution(executionType);

            //需要多线程启动执行器
            if (this->executionStartInformationsVector[i].needToThreadStart()) threadExecution->addThreadExecution(startExecution);

            //不需要多线程启动执行器
            else startExecution->start();

        }

        return true;

    }


    /**
     *重写关闭回调函数
     * @return
     */
    bool closeCallBackFunction() override {

        //关闭多线程执行器
        ((ClientThreadExecution*)this->m_executionsMap[ClientType::CLIENT_THREAD_EXECUTION])->close();


        return true;
    }


    public:

    ClientMainExecution()  = default;
    ~ClientMainExecution() = default;



    /**
     *
     * @return
     */
    ClientType::EXECUTION_TYPE getType() const override {
        return ClientMainExecution::executionType;
    }


    /**
     * 根据执行器类型获取执行器
     * @param executionType
     * @return
     */
    ClientExecutionInterface* getExecutionByExecutionType(ClientType::EXECUTION_TYPE executionType){
        auto it = this->m_executionsMap.find(executionType);
        return it == this->m_executionsMap.end()? nullptr : it->second;
    }


    /**
     *装配执行器
     * @tparam EXE
     * @tparam EXES
     * @param execution
     * @param executions
     */
    template<typename EXE = ClientExecutionInterface,  typename  ...EXES>
    void assemblyExecutions(EXE* execution ,EXES*... executions) {

        //类型是否为 ClientExecutionInterface
        if (!std::is_same<EXE, ClientExecutionInterface>::value) return;


        //设置主执行器
        execution->setMainExecution(this);

        //装配执行器
        this->m_executionsMap[execution->getType()] = execution;

        //递归调用执行函数
        this->assemblyExecutions(executions...);

    }










};


ClientType::EXECUTION_TYPE ClientMainExecution::executionType = ClientType::EXECUTION_TYPE::CLIENT_MAIN_EXECUTION;

/**
 * 执行器启动信息（主执行器会按顺序读取启动执行器）
 */
const std::vector<ExecutionStartInformation> ClientMainExecution::executionStartInformationsVector = {
    //配置执行器
    ExecutionStartInformation(ClientType::CLIENT_CONFIG_EXECUTION,false)
};

